﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using MongoDB.Driver;
using MongoDB.Bson;
using MongoDB.Driver.Builders;
using System.Configuration;

namespace DataAccessObject.NoSql
{
    /// <summary>
    /// MongoDB数据库操作类。
    /// </summary>
    public static class MongoDBHelper
    {
        /// <summary>
        /// 数据库连接串 mongodb://172.16.61.218:27017
        /// </summary>
        private static readonly string connectionString = ConfigurationManager.AppSettings["MongoDB"];

        #region 初始化
        /// <summary>
        /// 获取数据库实例对象
        /// </summary>
        /// <param name="connectionString">数据库连接串</param>
        /// <param name="dbName">数据库名称</param>
        /// <returns>数据库实例对象</returns>
        private static MongoDatabase GetDatabase(string dbName)
        {
            MongoClient client = new MongoClient(connectionString);
            var server = client.GetServer();
            return server.GetDatabase(dbName);
        }

        #endregion

        #region  插入操作

        /// <summary>
        /// 插入一条记录
        /// </summary>
        /// <typeparam name="T">数据类型</typeparam>
        /// <param name="connectionString"></param>
        /// <param name="dbName">数据名称</param>
        /// <param name="collectionName">集合名称</param>
        /// <param name="model">数据对象</param>
        public static void Insert<T>(string dbName, string collectionName, T model)
        {
            if (model == null) { throw new ArgumentNullException("model", "待插入数据不能为空"); }

            try
            {
                var db = GetDatabase(dbName);
                var collection = db.GetCollection<T>(collectionName);
                //在x字段上添加一个唯一索引。
                //collection.EnsureIndex(IndexKeys.Ascending("x"), IndexOptions.SetUnique(true));
                //MongoInsertOptions options = new MongoInsertOptions
                //{
                //    Flags = InsertFlags.ContinueOnError//插入过程出现错误时，继续插入后面的元素。
                //};
                collection.Insert(model);
                //collection.Insert(model, options);
            }
            catch (Exception ex)
            {
                throw ex;
            }


        }

        #endregion

        #region 更新操作

        /// <summary>
        /// 更新数据
        /// </summary>
        /// <param name="dbName">数据库名称</param>
        /// <param name="collectionName">集合名称</param>
        /// <param name="query">查询条件</param>
        /// <param name="dictUpdate">更新字段</param>
        public static void Update(string dbName, string collectionName, IMongoQuery query, Dictionary<string, BsonValue> dictUpdate)
        {
            try
            {
                var db = GetDatabase(dbName);
                var collection = db.GetCollection(collectionName);
                var update = new UpdateBuilder();
                if (dictUpdate != null && dictUpdate.Count > 0)
                {
                    foreach (var item in dictUpdate)
                    {
                        update.Set(item.Key, item.Value);
                    }
                }
                collection.Update(query, update, UpdateFlags.Multi);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 更新数据
        /// </summary>
        /// <param name="dbName">数据库名称</param>
        /// <param name="collectionName">集合名称</param>
        /// <param name="query">查询条件</param>
        /// <param name="update">更新条件</param>
        public static void Update(string dbName, string collectionName, IMongoQuery query, IMongoUpdate update)
        {
            try
            {
                var db = GetDatabase(dbName);
                var collection = db.GetCollection(collectionName);
                collection.Update(query, update, UpdateFlags.Multi);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        #endregion

        #region 删除操作

        /// <summary>
        /// 删除集合中符合条件的数据
        /// </summary>
        /// <param name="connectionString">数据库连接串</param>
        /// <param name="dbName">数据库名称</param>
        /// <param name="collectionName">集合名称</param>
        /// <param name="query">查询条件</param>
        public static void DeleteByCondition(string dbName, string collectionName, IMongoQuery query)
        {
            try
            {
                var db = GetDatabase(dbName);
                var collection = db.GetCollection(collectionName);
                collection.Remove(query);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 删除集合中的所有数据
        /// </summary>
        /// <param name="dbName">数据库名称</param>
        /// <param name="collectionName">集合名称</param>
        public static void DeleteAll(string dbName, string collectionName)
        {
            try
            {
                var db = GetDatabase(dbName);
                var collection = db.GetCollection(collectionName);
                collection.RemoveAll();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        #endregion

        #region 查询操作

        /// <summary>
        /// 根据ID获取数据对象
        /// </summary>
        /// <typeparam name="T">数据类型</typeparam>
        /// <param name="dbName">数据库名称</param>
        /// <param name="collectionName">集合名称</param>
        /// <param name="id">ID</param>
        /// <returns>数据对象</returns>
        public static T GetById<T>(string dbName, string collectionName, string id)
        {
            try
            {
                var db = GetDatabase(dbName);
                var collection = db.GetCollection<T>(collectionName);
                var tId = new ObjectId(id);
                return collection.FindOneById(tId);
            }
            catch (Exception ex)
            {
                throw ex;
            }

        }

        /// <summary>
        /// 根据查询条件获取一条数据
        /// </summary>
        /// <typeparam name="T">数据类型</typeparam>
        /// <param name="dbName">数据库名称</param>
        /// <param name="collectionName">集合名称</param>
        /// <param name="query">查询条件</param>
        /// <returns>数据对象</returns>
        public static T GetOneByCondition<T>(string dbName, string collectionName, IMongoQuery query)
        {
            try
            {
                var db = GetDatabase(dbName);
                var collection = db.GetCollection<T>(collectionName);
                return collection.FindOne(query);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 根据查询条件获取多条数据
        /// </summary>
        /// <typeparam name="T">数据类型</typeparam>
        /// <param name="dbName">数据库名称</param>
        /// <param name="collectionName">集合名称</param>
        /// <param name="query">查询条件</param>
        /// <returns>数据对象集合</returns>
        public static List<T> GetManyByCondition<T>(string dbName, string collectionName, IMongoQuery query)
        {
            try
            {
                var db = GetDatabase(dbName);
                var collection = db.GetCollection<T>(collectionName);
                return collection.Find(query).ToList();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 根据查询条件获取多条数据（分页）
        /// </summary>
        /// <typeparam name="T">数据类型</typeparam>
        /// <param name="dbName">数据库名称</param>
        /// <param name="collectionName">集合名称</param>
        /// <param name="query">查询条件</param>
        /// <param name="sortBy">排序</param>
        /// <param name="pageIndex">页号</param>
        /// <param name="pageSize">每页大小</param>
        /// <returns>分页数据集合</returns>
        //public static Paging<T> GetManyByPageCondition<T>(string dbName, string collectionName, IMongoQuery query, IMongoSortBy sortBy, int pageIndex, int pageSize)
        //{
        //    try
        //    {
        //        var db = GetDatabase(dbName);
        //        var collection = db.GetCollection<T>(collectionName);
        //        var result = new Paging<T>();
        //        result.totalCount = (int)collection.Count(query);
        //        result.item = collection.Find(query).SetSortOrder(sortBy).SetSkip((pageIndex - 1) * pageSize).SetLimit(pageSize).ToList();
        //        return result;
        //    }
        //    catch (Exception ex)
        //    {
        //        throw ex;
        //    }
        //}

        /// <summary>
        /// 获取集合中的所有数据
        /// </summary>
        /// <typeparam name="T">数据类型</typeparam>
        /// <param name="dbName">数据库名称</param>
        /// <param name="collectionName">集合名称</param>
        /// <returns>数据对象集合</returns>
        public static List<T> GetAll<T>(string dbName, string collectionName)
        {
            try
            {
                var db = GetDatabase(dbName);
                var collection = db.GetCollection<T>(collectionName);
                return collection.FindAll().ToList();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        #endregion
    }
}
